﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Web.Security;

namespace Brjostagjof_H4.Models
{
    public class MonsterRepository : IMonsterRepository
    {
        /*
         * TODO: Birtir index greinar og fréttir í réttri röð? - VB
         * TODO: Forma title á greinum í preview - VB
         */

        BrjostagjofDBDataContext db = new BrjostagjofDBDataContext();
        LatestFormat format = new LatestFormat();

        public void updateBan(string user, bool isUserActive)
        {
            var result = (from u in db.aspnet_Memberships
                          where u.aspnet_User.UserName == user
                          select u).SingleOrDefault();

            result.isActive = isUserActive;

            db.SubmitChanges();
        }

        public UserHandling getUserEditByUserName(string userName)
        {
            try
            {
                UserHandling result = (from u in db.UserHandlings
                                       where u.UserName.ToLower() == userName.ToLower()
                                       select u).SingleOrDefault();

                if (result.isActive == null)
                    result.isActive = true;

                return result;
            }
            catch (Exception)
            {
               
            }

            return null;
        }

        public List<UserHandling> getUserEditList()
        {
            List<UserHandling> returnList = new List<UserHandling>();

            var result = from user in db.UserHandlings
                         select user;

            foreach (var item in result)
            {
                if (item.isActive == null)
                    item.isActive = true;

                returnList.Add(item);
            }

            return returnList;
        }

        public bool isUserRegistered(string userName)
        {
            var result = (from u in db.aspnet_Users
                          where u.LoweredUserName == userName.ToLower()
                          select u).SingleOrDefault();

            if (result != null)
                return true;

            return false;
        }

        public bool updateRole(string userName, string role)
        {
            Guid userGuid = (from u in db.aspnet_Users
                              where u.LoweredUserName == userName.ToLower()
                              select u.UserId).SingleOrDefault();

            if (userGuid != null)
            {
                Guid roleGuid = (from u in db.aspnet_Roles
                                 where u.RoleName == role
                                 select u.RoleId).SingleOrDefault();

                aspnet_UsersInRole userRole = (from u in db.aspnet_UsersInRoles
                                               where u.UserId == userGuid
                                               select u).SingleOrDefault();

                if (userRole == null) // If user is not in a role
                                    // then a new object UsersInRole is created
                {
                    aspnet_UsersInRole newUser = new aspnet_UsersInRole();
                    newUser.UserId = userGuid;
                    newUser.RoleId = roleGuid;

                    db.aspnet_UsersInRoles.InsertOnSubmit(newUser);
                    db.SubmitChanges();

                    return true;
                }
                else if (userRole.RoleId != roleGuid) // If the user is not already in
                                                    // the requested role
                {
                    userRole.RoleId = roleGuid;
                    db.SubmitChanges();

                    return true;
                }

                return false;
            }
            else
                return false;
        } // updateRole ends

        public void updateCategories(List<Category> cats)
        {
            try
            {
                var result = from c in db.Categories
                             select c;

                int counter = 0;
                foreach (var item in result)
                    item.category_name = cats[counter].category_name;

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// Updates content in the Pharmacist section
        /// </summary>
        /// <param name="newAbout">The new content</param>
        /// <param name="user">Which user updates the section</param>
        public void updatePharmacist(About newPhar, string user)
        {
            try
            {
                About result = (from a in db.Abouts
                                where a.ID == 2
                                select a).SingleOrDefault();

                result = newPhar ;
                result.changed_by = user;
                result.date_changed = DateTime.Now;

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// Gets current content in Pharmacist section
        /// </summary>
        /// <returns>Pharmacist object</returns>
        public About getPharmacist()
        {
            About phar = (from a in db.Abouts
                               where a.ID == 2
                               select a).SingleOrDefault();

            return phar;
        }
        /// <summary>
        /// Updates content in the Donate section
        /// </summary>
        /// <param name="newDon">The new content</param>
        /// <param name="user"> Which user updates the section</param>
        public void updateDonate(About newDon, String user)
        {
            try
            {
                About result = (from a in db.Abouts
                                where a.ID == 5
                                select a).SingleOrDefault();

                result = newDon;
                result.changed_by = user;
                result.date_changed = DateTime.Now;

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Gets current content in Donate section
        /// </summary>
        /// <returns>Donate object</returns>
        public About getDonate()
        {
            About don = (from a in db.Abouts
                         where a.ID == 5
                         select a).SingleOrDefault();

            return don;
        }

        /// <summary>
        /// Updates content in the About section
        /// </summary>
        /// <param name="newAbout">The new content</param>
        /// <param name="user">Which user updates the section</param>
        public void updateAbout(About newAbout, string user)
        {
                try
                {
                    About result = (from a in db.Abouts
                                    where a.ID == 1
                                    select a).SingleOrDefault();

                    result = newAbout;
                    result.changed_by = user;
                    result.date_changed = DateTime.Now;

                    db.SubmitChanges(); 
                }
                catch (Exception e)
                {             
                    throw e;
                }
        }

        /// <summary>
        /// Gets current content of the About section
        /// </summary>
        /// <returns>About object</returns>
        public About getAbout()
        {
            About result = (from a in db.Abouts
                            where a.ID == 1
                          select a).SingleOrDefault();

            return result;
        }

        /// <summary>
        /// Gets a list of the latest news in preview style, formatted
        /// </summary>
        /// <param name="howMany">How many news previewes to get</param>
        /// <returns>List of the object Entry</returns>
        public List<Entry> getNewsPreview(int howMany)
        {
            try
            {
                List<Entry> returnList = new List<Entry>();

                var result = (from news in db.Entries
                              where news.entry_type == 2
                              orderby news.posted descending
                              select news).Take(howMany);

                foreach (var item in result)
                {
                    Entry temp = new Entry();

                    temp = item;
                    temp = format.formatNews(temp);

                    returnList.Add(temp);
                }

                return returnList;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// Gets news from ID
        /// </summary>
        /// <param name="id">ID of news to get</param>
        /// <returns>Entry object</returns>
        public Entry getNewsFromID(int id)
        {
            try
            {
                Entry result = (from news in db.Entries
                                where news.entry_type == 2 &&
                                news.ID == id
                                orderby news.posted ascending
                                select news).SingleOrDefault();

                return result;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// Gets id and title of articles only
        /// </summary>
        /// <param name="cat">Category ID</param>
        /// <returns>List of Entry</returns>
        public List<Entry> getArticleList(int cat)
        {
            List<Entry> returnList = new List<Entry>();

            var result = from art in db.Entries
                         where art.category == cat
                         orderby art.posted ascending
                         select art;

            foreach (var item in result)
            {
                Entry temp = new Entry();
                temp.ID = item.ID;
                temp.title = item.title;

                returnList.Add(temp);
            }

            return returnList;
        }

        /// <summary>
        /// Gets all categories in database
        /// </summary>
        /// <returns>List of Category object</returns>
        public List<Category> getCategories()
        {
            List<Category> returnList = new List<Category>();

            var result = from cat in db.Categories
                         select cat;

            foreach (var item in result)
            {
                Category cat = new Category();
                cat.ID = item.ID;
                cat.category_name = item.category_name;

                returnList.Add(cat);
            }

            return returnList;
        }

        /// <summary>
        /// Gets category ID from category name
        /// </summary>
        /// <param name="category">Name of category to retrieve</param>
        /// <returns>Int ID for category</returns>
        public int getCategoryID(string category)
        {
            int result = (from cat in db.Categories
                          where cat.category_name == category
                          select cat.ID).SingleOrDefault();

            return result;
        }

        /// <summary>
        /// Gets name of category from category ID
        /// </summary>
        /// <param name="catID">ID of category to retrieve</param>
        /// <returns></returns>
        public string getCategoryName(int catID)
        {
            string result = (from cat in db.Categories
                             where cat.ID == catID
                             select cat.category_name).SingleOrDefault();

            return result;
        }

        /// <summary>
        /// Gets preview of latest articles for displaying in category-preview list (Articles.aspx)
        /// </summary>
        /// <param name="howMany">Denotes how many articles you want returned from each category</param>
        /// <returns>List of Entry without content</returns>
        public List<Entry> getArticlePreview(int howMany)
        {
            List<Entry> returnList = new List<Entry>();
            var randomizer = new Random();

            int highestCat = int.Parse(
                        (from c in db.Entries
                         where c.entry_type == 1
                         select c.category).Max().ToString());

            for (int i = 0; i < highestCat; i++) // Go through all categories and gets random articles for each category
            {
                var result = (from entry in db.Entries
                              where entry.entry_type == 1 &&
                              entry.category == (i + 1)
                              orderby entry.posted ascending
                              select entry).Take(howMany);


                foreach (var item in result)
                {
                    Entry temp = new Entry();
                    temp = item;
                    temp.content = "x";

                    returnList.Add(temp);
                }
            } // for loop ends

            return returnList;
        }

        /// <summary>
        /// Gets entry from ID
        /// </summary>
        /// <param name="id">ID of entry to retrieve</param>
        /// <returns>Entry object</returns>
        public Entry getEntryById(int id)
        {
            var result = (from entry in db.Entries
                          where entry.ID == id
                          select entry).SingleOrDefault();

            return result;
        }

        /// <summary>
        /// Gets a list of latest news entries
        /// </summary>
        /// <param name="number">How many news entries to retrieve</param>
        /// <returns>List of Entry object</returns>
        public List<Entry> getXLatestNews(int number)
        {
            List<Entry> lstNews = new List<Entry>();
            Entry entry = new Entry();

            var result = (from n in db.Entries
                          where n.entry_type == 2 // Denotes entry as 'News'
                          orderby n.posted ascending
                          select n).Take(number);

            foreach (var n in result)
                lstNews.Add(n);

            lstNews = format.formatEntries(lstNews); // News formatted to fit the index page

            return lstNews;
        }

        /// <summary>
        /// Gets the latest articles
        /// </summary>
        /// <param name="number">How many articles to retrieve</param>
        /// <returns>List of Entry object</returns>
        public List<Entry> getXLatestArticles(int number)
        {
            List<Entry> lstEntries = new List<Entry>();
            Entry entry = new Entry();

            var result = (from n in db.Entries
                          where n.entry_type == 1 // Denotes entry as an 'Article'
                          orderby n.posted ascending
                          select n).Take(number);

            int cnt = result.Count();

            foreach (var n in result)
                lstEntries.Add(n);

            lstEntries = format.formatEntries(lstEntries); // Article formatted to fit the index page

            return lstEntries;
        }

        /// <summary>
        /// Get the desired number of entries in descending order by posted date, 
        /// irrelevant of their type, category or status.
        /// </summary>
        /// <param name="number">Desired number of entries.</param>
        /// <returns></returns>
        public List<Entry> getXLatestEntries(int number)
        {
            List<Entry> resultList = new List<Entry>();
            var result = (from e in db.Entries
                          where e.entry_status == 1 || e.entry_status == 2
                          orderby e.posted descending
                          select e).Take(number);

            foreach (var e in result)
                resultList.Add(e);

            return resultList;
        }

        /// <summary>
        /// Get the desired number of entries by the given user, in descending order by posted date.
        /// </summary>
        /// <returns>Desired number of entries by the user.</returns>
        public List<Entry> getXLatestEntriesByID(int number, Guid ID)
        {
            List<Entry> resultList = new List<Entry>();
            var result = (from e in db.Entries
                          where e.added_by == ID && e.entry_status != 3
                          orderby e.posted descending
                          select e).Take(number);

            foreach (var e in result)
                resultList.Add(e);

            return resultList;
        }

        public IEnumerable<aspnet_Membership> getProfiles()
        {
            var result = from n in db.aspnet_Memberships
                         select n;

            return result;
        }

        public aspnet_Membership getProfileByUserName(string userName)
        {
            var result1 = (from u in db.aspnet_Users
                           where u.UserName == userName
                           select u).SingleOrDefault();
            var result2 = (from p in db.aspnet_Memberships
                           where p.UserId == result1.UserId
                           select p).SingleOrDefault();

            return result2;
        }

        /// <summary>
        /// Gets the username
        /// </summary>
        /// <param name="ID">The Guid userId</param>
        /// <returns>The username as a string</returns>
        public string getUserNameByID(Guid? ID)
        {
            var result = (from c in db.aspnet_Users
                          where c.UserId == ID
                          select c.UserName).SingleOrDefault().ToString();
            return result;
        }

        /// <summary>
        /// Update profile to DB
        /// </summary>
        /// <param name="p">aspnet_Membership</param>
        public void updateProfile(aspnet_Membership p, string user)
        {
            aspnet_Membership oldProfile = getProfileByUserName(user);
            if (oldProfile != null)
            {
                oldProfile.Email = p.Email;
                oldProfile.LoweredEmail = p.Email;
                oldProfile.phone_number = p.phone_number;
                oldProfile.title = p.title;
                oldProfile.fullName = p.fullName;

                db.SubmitChanges();
            }
        }

        /// <summary>
        /// Add contact us data to DB
        /// </summary>
        /// <param name="n">Contact</param>
        /// 
        internal void addContactUsData(ContactModel n)
        {
            ContactUs c = new ContactUs();
            c.posted = DateTime.Now;
            c.unread = true;
            c.subj = n.subj;
            c.txt = n.txt;
            c.email = n.email;
            db.ContactUs.InsertOnSubmit(c);
            db.SubmitChanges();
        }
        public ContactUs deleteContactUsData(int id)
        {
            var result = (from n in db.ContactUs
                          where n.ID == id
                          select n).First();
            db.ContactUs.DeleteOnSubmit(result);
            db.SubmitChanges();
            return result;
        }

        /// <summary>
        /// View Detailed contact us submission
        /// update unread property
        /// </summary>
        /// <param name="id">int</param>
        /// <returns>ContactUs</returns>
        public ContactUs fetchContactUsById(int id)
        {
            var result = (from n in db.ContactUs
                          where n.ID == id
                          orderby n.posted descending
                          select n).SingleOrDefault();
            if (result.unread == true)
            { //So I can use this for other methods without constant update
                result.unread = false;
                db.SubmitChanges();
            }
            return result;
        }
        /// <summary>
        /// Fetch contact us queries
        /// </summary>
        /// <returns></returns>
        public IQueryable<ContactUs> fetchContactUsDataAll()
        {
            var result = from n in db.ContactUs
                         where n.unread == true
                         orderby n.posted descending
                         select n;
            return result;
        }
        /// <summary>
        /// Fetch old contact us queries
        /// </summary>
        /// <returns></returns>
        public IQueryable<ContactUs> fetchContactUsDataOld()
        {
            var result = from n in db.ContactUs
                         where n.unread == false
                         orderby n.posted descending
                         select n;
            return result;
        }

        /// <summary>
        /// Inserting a new entry into the database.
        /// Takes an EntryModel object and copies its data into a new Entry object which is 
        /// inserted into the database.
        /// </summary>
        /// <param name="entry">The entry object from the page form.</param>
        public void addEntry(EntryModel entry)
        {
            Entry e = new Entry();
            e.posted = DateTime.Now;
            e.added_by = entry.userId;
            e.title = entry.title;
            e.content = entry.content;
            e.category = entry.category;
            e.entry_type = entry.entry_type;
            e.entry_status = entry.entry_status;

            db.Entries.InsertOnSubmit(e);
            db.SubmitChanges();
        }

        /// <summary>
        /// Updates the title, category, content and entry type of an entry.
        /// </summary>
        /// <param name="entry">The Entry model that should be updated.</param>
        public void updateEntry(Entry entry)
        {
           Entry oldVersion = getEntryById(entry.ID);
            if (oldVersion != null)
            {
                // TODO olig - add an "updated" field in the Entries table?
                oldVersion.title = entry.title;
                oldVersion.category = entry.category;
                oldVersion.content = entry.content;
                oldVersion.entry_type = entry.entry_type;
                oldVersion.entry_status = entry.entry_status;
                db.SubmitChanges();
            }
        }

        //public List<Question> getXLatestQuestions(int number)
        //{
        //    List<Question> resultList = new List<Question>();
        //    var result = (from e in db.Questions
        //                  where e.answered_date != null
        //                  orderby e.posted descending
        //                  select e).Take(number);

        //    foreach (var e in result)
        //        resultList.Add(e);
            
        //    return resultList;
        //} 

        public Guid getUserIDByName(String name)
        {
            var id = (from i in db.aspnet_Users
                      where i.UserName == name
                      select i.UserId).SingleOrDefault();

            return id;
        }

        public Timeline getDataByUserID(Guid user)
        {
            var line = (from l in db.Timelines
                        where l.created_by == user
                        orderby l.ID descending
                        select l).FirstOrDefault();
            return line;
        }

        public void addTimelineData(Timeline t)
        {
            db.Timelines.InsertOnSubmit(t);
            db.SubmitChanges();
        }

        public int getChartIDSequence()
        {
            var result = (from d in db.Timelines
                          select d.chartID).Max()+1;
            return result;
        }
        public void addAdvertisement(AdsModels ads)
        {
            Advertisement an = new Advertisement();
            an.posted = DateTime.Now;
            an.isdisplayed = true;
            an.title = ads.adtitle;
            an.txt = ads.adtxt;
            an.url = ads.adimgurl;
            db.Advertisements.InsertOnSubmit(an);
            db.SubmitChanges();

        }
        //Not in use
        public string displayAdevertisement(int id)
        {
            var result = (from n in db.Advertisements
                          where n.ID == id
                          &&
                          n.isdisplayed == true
                          select n.url).SingleOrDefault();
            return result;
        }
    }
}